package com.zx.jhpt.service;

import com.zx.framework.core.exception.ServiceException;
import com.zx.framework.core.pagination.Pagination;
import com.zx.framework.core.util.DatetimeUtils;
import com.zx.framework.core.util.RandomUtil;
import com.zx.framework.core.util.SQLBuilder;
import com.zx.framework.core.util.StringUtil;
import com.zx.framework.db.IBaseDAO;
import com.zx.framework.plat.dept.po.Dept;
import com.zx.framework.plat.dept.service.DeptService;
import com.zx.framework.plat.user.po.User;
import com.zx.framework.plat.user.service.UserService;
import com.zx.jhpt.excel.Engine;
import com.zx.jhpt.excel.vo.Column;
import com.zx.jhpt.excel.vo.Risk;
import com.zx.jhpt.po.*;
import com.zx.jhpt.util.DeptCache;
import com.zx.jhpt.util.FxdCache;
import com.zx.jhpt.vo.JhptConts;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service("engineService")
@Transactional
public class EngineService {
	private static final Logger LOGGER = Logger.getLogger(EngineService.class);
	@Resource
	private IBaseDAO baseDAO;
	@Resource
	private FxDeptService fxDeptService;
	@Resource
	private DeptService deptService;
	@Resource
	private UserService userService;
	//需要指定台账到人的部门
	public static final String assignDept="HB.SJ.YZ";
	
	/**
	 * 执行建表语句
	 * @param sql
	 * @return
	 */
	public int executeCreateSQL(final String sql){
		String[] sqlArr = sql.split(";");
		for (String string : sqlArr) {
			if(StringUtil.isNotBlank(string)){
				baseDAO.executeSQL(string);
			}
		}
		return sqlArr.length;
	}
	/**
	 * 判断表是否存在
	 * @param tbName
	 * @return
	 */
	public boolean exists(String tbName){
		String sql  = "select count(*) from user_tables where table_name like ?";
		return baseDAO.getSQLUnique(sql, BigDecimal.class, tbName).intValue() !=0;
	}
	/**
	 * 保存详单及生产台账信息
	 * @param risk 风险
	 * @param rs 数据
	 * @param cycle 风险周期
	 */
	public void saveDatas(Risk risk,List<Object[]> rs,String cycle){
		String sql = Engine.getSql(risk);
		try {
            // 移除本周期此风险点旧数据
            baseDAO.executeSQL("delete from "+risk.getTbName()+" where fxid=? and cycle=? ",risk.getFxid(),cycle);
            baseDAO.executeSQL("delete from REPLYMESSAGE where FXID=? and HCSJ=? ",risk.getFxid(),DatetimeUtils.stringToDate(cycle,"yyyy-MM"));

			//获取详单数据
			List<String> deptIds = new ArrayList<String>();
			int deptIndex = risk.getDeptIndex();
			//业支用户
			List<String> assignUserIds = new ArrayList<String>();
			for (Object[] o : rs) {
				
				String deptId = (String) o[deptIndex];
				//保存不重复的部门编码
				if(!deptIds.contains(deptId)){
					deptIds.add(deptId);
				}
				//如果设置了业支分发人员的字段名称
				if(StringUtil.isNotEmpty(risk.getAssign())){
					int assignIndex =Engine.getAssignIndex(risk);
					if(assignIndex!=-1){
						String tempAssign = (String) o[assignIndex];
						if(!assignUserIds.contains(tempAssign)){
							assignUserIds.add(tempAssign);
						}
					}
					
				}
				 
				//创建参数对象数组
                List<Object> params = new ArrayList<Object>();
                for(Object o1:o){
                    params.add(o1);
                }
                params.add(RandomUtil.getUUID());
				params.add(risk.getFxid());
				params.add(cycle);
				baseDAO.executeSQL(sql, params.toArray());
			}
			//获取该风险点对应的部门
			List<FxDept> fxDepts = fxDeptService.findFxDept(risk.getFxid());
			Map<String, String> userNames = new HashMap<String, String>();
			//保存台账信息
			for (FxDept fxDept : fxDepts) {
				
				String tempDept = fxDept.getId().getDept();
				Dept d = DeptCache.getDept(tempDept);
				Fxfkjz fxd = FxdCache.get(risk.getFxid());
				Dept dept = deptService.findDeptById(tempDept);
                List<User> users = fxDeptService.findFxUsers(risk.getFxid(),tempDept);
                String tmpUsers = "";
                for(User user:users){
                    tmpUsers += user.getUserName()+",";
                }
                if(tmpUsers.length()>0){
                    tmpUsers = tmpUsers.substring(0,tmpUsers.length()-1);
                }
                //如果是业务支撑
				if(!assignUserIds.isEmpty() && tempDept.equals(assignDept)){
					for (String assignId : assignUserIds) {
						Replymessage rm = new Replymessage();
						String showName = "未知";
						User u  = null;
						if(!userNames.containsKey(assignId)){
							u  = userService.findUserById(assignId);
							if(u!=null){
								showName = u.getUserName();
								userNames.put(assignId, showName);
							}
						}else{
							showName= userNames.get(assignId);
						}
						rm.setDeptid(tempDept);
						
						if(d!=null){
							rm.setDeptname(d.getName());
						}
						
		                rm.setGdwfzr(showName);
						rm.setGdwzgld(dept.getRemark());
						rm.setFxid(risk.getFxid());
						rm.setHcsj(DatetimeUtils.stringToDate(cycle,"yyyy-MM"));
						rm.setId(RandomUtil.getUUID());
		                rm.setStatus(JhptConts.RM_STATUS_RUN);
						if(deptIds.contains(fxDept.getId().getDept())){
							if(fxd!=null){
								rm.setFxwt(fxd.getFxdmc());
							}
							
						}else{
							rm.setFxwt("无");
							rm.setGdwfkjg("无");
		                    rm.setStatus(JhptConts.RM_STATUS_FIN);
						}
						baseDAO.save(rm);
						//保存业支人员和台账的关系
						ReplyUser ru = new ReplyUser(new ReplyUserId(rm.getId(), cycle, assignId));
						baseDAO.save(ru);
					}
				}else{
					Replymessage rm = new Replymessage();
					
					rm.setDeptid(tempDept);
					
					if(d!=null){
						rm.setDeptname(d.getName());
					}
					
	                rm.setGdwfzr(tmpUsers);
					rm.setGdwzgld(dept.getRemark());
					rm.setFxid(risk.getFxid());
					rm.setHcsj(DatetimeUtils.stringToDate(cycle,"yyyy-MM"));
					rm.setId(RandomUtil.getUUID());
	                rm.setStatus(JhptConts.RM_STATUS_RUN);
					if(deptIds.contains(fxDept.getId().getDept())){
						if(fxd!=null){
							rm.setFxwt(fxd.getFxdmc());
						}
						
					}else{
						rm.setFxwt("无");
						rm.setGdwfkjg("无");
	                    rm.setStatus(JhptConts.RM_STATUS_FIN);
					}
					baseDAO.save(rm);
				}
				
			}
			
		} catch (Exception e) {
			LOGGER.error(e);
			throw new ServiceException("风险详情及台账保存失败！");
		}
	}

	/**
	 * 分页获取风险详单
	 * @param risk 风险
	 * @param cycle 周期
	 * @param deptid 部门ID
	 * @param page 页码
	 * @param rows 每页数据量
     * @return 分页风险详单
     */
    public  Pagination<Map> page(Risk risk,String userId,
                       String cycle,
                       String deptid,
                       Integer page,
                       Integer rows){

        String sql = "select * from " + risk.getTbName() + " t where 1=1 " ;
        String cntSql = "select count(*) from " + risk.getTbName() + " t where 1=1 " ;
        List<Object> params = new ArrayList<>();
        List<String> clauses = new ArrayList<>();

        clauses.add(" and t.cycle=? ");
        params.add(cycle);

        clauses.add(" and t.gsbm=? ");
        params.add(deptid);

        clauses.add(" and t.fxid=? ");
        params.add(risk.getFxid());
        
        if(StringUtil.isNotEmpty(risk.getAssign())){
        	Column c = risk.getColumns().get(Engine.getAssignIndex(risk));
        	clauses.add(" and t."+c.getId()+"=?");
            params.add(userId);
        }
        
        if (!clauses.isEmpty()) {
            String where = SQLBuilder.appendSQL(clauses);
            sql += where;
            cntSql += where;
        }

        sql += " order by t.fxid ";
        return baseDAO.sqlPageQuery(sql,cntSql,page,rows,params.toArray());
    }

    /**
     * 获取风险详单
     * @param risk 风险
     * @param cycle 周期
     * @param deptid 部门ID
     * @return 分页风险详单
     */
    public  List<Map> list(Risk risk,
                                 String cycle,
                                 String deptid
    ){

        String sql = "select * from " + risk.getTbName() + " t where 1=1 " ;
        List<Object> params = new ArrayList<>();
        List<String> clauses = new ArrayList<>();

        clauses.add(" and t.cycle=? ");
        params.add(cycle);

        clauses.add(" and t.gsbm=? ");
        params.add(deptid);

        clauses.add(" and t.fxid=? ");
        params.add(risk.getFxid());

        if (!clauses.isEmpty()) {
            String where = SQLBuilder.appendSQL(clauses);
            sql += where;
        }

        sql += " order by t.fxid ";
        return baseDAO.querySQL(sql,params.toArray());
    }
    
    /**
     * 获取数据
     * @param risk
     * @param cycle 周期
     * @return
     */
	public List<Map<String,Object>> loadDatas(Risk risk,String cycle){
		String sql = "select * from " + risk.getTbName() +" where cycle = ?";
		return baseDAO.querySQL(sql, cycle);
	}
}
